package com.nulldev.util.web.flexibleKit.scfk;

import java.time.Duration;
import java.util.Collections;
import java.util.Map;

import com.nulldev.util.data.Variables;
import com.nulldev.util.data.Arrays.maps.FastMaps;
import com.nulldev.util.web.URLUtils.Entry;
import com.nulldev.util.web.URLUtils.URLUtils;
import com.nulldev.util.web.URLUtils.fparser.URL;
import com.nulldev.util.web.URLUtils.fparser.exceptions.MalformedURLException;
import com.nulldev.util.web.flexibleKit.scfk.protocols.PreferredProtocol;
import com.nulldev.util.web.flexibleKit.scfk.protocols.RedirectionPolicy;
import com.nulldev.util.web.flexibleKit.scfk.utils.ChannelTOSType;

public class SCFKRequest {

	private static final String[][] DEFAULT_HEADERS = new String[][]
		{
				{ "User-Agent", URLUtils.STANDARD_USERAGENT },
				{ "Accept", "*/*" },
				{ "Accept-Language", "en-us,en;q=0.5" },
				{ "Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7" },
				{ "Accept-Encoding", "gzip, deflate" }, };

	private URL url;
	private final Map<String, String> headers = FastMaps.map(15, DEFAULT_HEADERS);
	private PreferredProtocol protocol = PreferredProtocol.HTTP_1_1;
	private HTTPRequestType method = HTTPRequestType.GET;
	private RedirectionPolicy redirPolicy = RedirectionPolicy.IF_SECURE;
	private ChannelTOSType tosType = ChannelTOSType.TOS_THROUGHPUT;
	private Object body;
	private Duration timeout;

	public SCFKRequest() {
		this.url = null;
	}

	public SCFKRequest(final URL url) {
		Variables.notNullE(url);
		this.url = url;
	}

	public SCFKRequest(final String url) {
		Variables.notNullE(url);
		try {
			this.url = URL.parse(url);
		} catch (MalformedURLException e) {
			throw new RuntimeException(e);
		}
	}

	public SCFKRequest(final java.net.URL url) {
		Variables.notNullE(url);
		try {
			this.url = URL.parse(url.toExternalForm());
		} catch (MalformedURLException e) {
			throw new RuntimeException(e);
		}
	}

	public URL getURL() {
		return this.url;
	}

	public PreferredProtocol getProtocol() {
		return this.protocol;
	}

	public String getHeader(final String item) {
		return this.headers.get(item);
	}

	public HTTPRequestType getMethod() {
		return this.method;
	}

	public RedirectionPolicy redirectionPolicy() {
		return this.redirPolicy;
	}

	public ChannelTOSType tosPolicy() {
		return this.tosType;
	}

	public SCFKRequest setRedirectionPolicy(final RedirectionPolicy policy) {
		Variables.notNullE(policy);
		this.redirPolicy = policy;
		return this;
	}

	public Map<String, String> headers() {
		return Collections.unmodifiableMap(this.headers);
	}

	public boolean hasHeader(final String item) {
		return this.headers.containsKey(item);
	}

	public Object body() {
		return this.body;
	}

	public SCFKRequest setBody(final Object o) {
		this.body = o;
		return this;
	}

	public void header(final String key, final String value) {
		if (key == null || key.isEmpty())
			return;
		if (value == null || value.isEmpty())
			return;
		this.headers.put(key, value);
	}

	public void header(final Entry entry) {
		if (entry == null || !entry.isValid())
			return;
		this.headers.put(entry.getKey(), entry.getValue());
	}

	public SCFKRequest updateURL(final URL url) {
		Variables.notNullE(url);
		this.url = url;
		return this;
	}

	public SCFKRequest setRequestType(final HTTPRequestType type) {
		Variables.notNullE(type);
		this.method = type;
		return this;
	}

	public Duration getTimeout() {
		return this.timeout;
	}

	public boolean hasTimeout() {
		return this.timeout != null;
	}

	public SCFKRequest setTimeout(final Duration dur) {
		this.timeout = dur;
		return this;
	}

	public SCFKRequest setPreferredProtocol(final PreferredProtocol prot) {
		Variables.notNullE(prot);
		this.protocol = prot;
		return this;
	}

	public SCFKRequest setTOSPolicy(final ChannelTOSType tos) {
		Variables.notNullE(tos);
		this.tosType = tos;
		return this;
	}
}
